#include <iostream>
#include <string.h>
#include <time.h>
#include <thread>

#include "MemPool.h"
#include "Singleton.h"
#include "Hashtable.h"

using namespace std;

class A {
    int a;
    int b;
    int m_len;
    char* m_ptr;

public:
    A(int len):m_len(len){
        m_ptr = new char[m_len];
    }

    ~A(){
        delete [] m_ptr;
    }

    char* getPtr(){
        return m_ptr;
    }
};

class B:public Singleton<B>{
    int a;
    int b;

public:
    B(){
        b = 1022;
        cout<<"B"<<endl;
    }
    ~B(){

    }

    void printB(){
        cout<<a<<endl;
    }
};


void test1(MemPool* pool){
    int i;
//    int n = 10000000;
    int n = 1;

    clock_t start,end;

    start = clock();
    for(i=0;i<n;i++){
        char* p = (char*)pool->_malloc(6);
        memcpy(p,"test12",sizeof("test12") - 1);
        pool->_free(p);
    }
    end = clock();

    cout<<end-start<<endl;

    start = clock();
    for(i=0;i<n;i++){
        char* p = (char*)pool->_calloc(6);
        memcpy(p,"test12",sizeof("test12") - 1);
        pool->_free(p);
    }
    end = clock();

    cout<<end-start<<endl;



    start = clock();
    for(i=0;i<n;i++){
        char* p = (char*)malloc(6);
        memcpy(p,"test12",sizeof("test12") - 1);
//        cout<<p<<endl;
        free(p);
    }
    end = clock();

    cout<<end-start<<endl;

}

void test2(){
    int i;
//    int n = 10000000;
    int n = 1;

    clock_t start,end;

    start = clock();
    for(i=0;i<n;i++){
        char* p = new char[5];
        memcpy(p,"test1",sizeof("test1") - 1);

        delete[] p;
    }
    end = clock();

    cout<<end-start<<endl;

    //////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////
    start = clock();
    for(i=0;i<n;i++){
        char* p = new char[5];
        memcpy(p,"test1",sizeof("test1") - 1);

        delete[] p;
    }
    end = clock();

    cout<<end-start<<endl;
}

void test3(){
    int len = 1345;
    while(1){
        A* a = new A(len);
        char* ptr = a->getPtr();

        memset(ptr,0,len);
        memcpy(ptr,"test123456",sizeof("test123456") - 1);

        delete a;
    }
}

void test4(){
    int k = 4*1024;
//    int k = 200;
    int len = 20;

    while(1){
        if(len > k)
            len = 20;
        len++ ;

        A* a = new A(len);
        char* ptr = a->getPtr();

        memset(ptr,0,len);
        memcpy(ptr,"test123456",sizeof("test123456") - 1);

        cout<<len<<":"<<ptr<<endl;

        delete a;
    }
}

void test4_(){
    int k = 4*1024;
//    int k = 200;
    int len = 20;

    while(1){
        if(len > k)
            len = 20;
        len++ ;

        A* a = new A(len);
        char* ptr = a->getPtr();

        memset(ptr,0,len);
        memcpy(ptr,"test123456",sizeof("test123456") - 1);

        cout<<len<<":"<<ptr<<endl;

        delete a;
    }
}

void test5(){
    std::thread t1(test4);
    std::thread t2(test4_);

    t1.join();
    t2.join();
}

void test6(){
    std::string s1("123456tstttdb");
    std::string s2(s1);
    cout<<s1.c_str()<<endl;
    cout<<s2.c_str()<<endl;
    cout<<"length:"<<s1.length()<<endl;
    cout<<sizeof(s1)<<endl;

    if(memcmp(&s2,&s1,sizeof(s1)) == 0){
        cout<<"s2:"<<s2.c_str()<<endl;
    }else{
        cout<<"s2 is not equal s1"<<endl;
    }

    char* ptr;
    int len = 17;
    A* a = new A(len);
    ptr = a->getPtr();

    memset(ptr,0,len);
    memcpy(ptr,"test123456",sizeof("test123456") - 1);

    A* aa = new A(len);
    ptr = aa->getPtr();

    memset(ptr,0,len);
    memcpy(ptr,"test123456",sizeof("test123456") - 1);

    if(memcmp(a,aa,sizeof(A)) == 0){
        cout<<"equal"<<endl;
    }else{
        cout<<"not equal"<<endl;
    }
}

void test7(){
    A a(3);
    A aa(5);

    A& b = a;

    A c = b;

    A* d = &b;
    A* e = &a;
}

Hashtable<std::string,std::string> ht;

void test8() {
//    Hashtable<std::string,std::string> ht;

    string s1 = "test1",v1 = "123";
    string s2 = "test2",v2 = "456";
    string s3 = "test2",v3 = "good";
    string s_1 = "test2";

    ht.insert(s1,v1);
    ht.insert(s2,v2);
    ht.insert(s3,v3);

    string* s4 = ht.get(s1);
    cout<<*s4<<endl;

    string* s5 = ht.get(s_1);
    if(s5)
        cout<<*s5<<endl;
    else
        cout<<"test8 not find"<<endl;
}

//unsigned int time33(const void* ptr,int n){
//    unsigned int hash = 0;
//    int i;
//    for(i=0;i<n;i++){
//        hash = hash * 33 + reinterpret_cast<const char*>(ptr)[i];
//    }

//    return hash;
//}

void test9() {
    string s = "12345";

    time33(s.c_str());
}

void test10() {
    Hashtable<int,int> ht;

    int i;
    int n = 10000000;
    int cnt = 1;

    while(cnt--) {
        for(i=0;i<n;i++) {
            ht.insert(i,i);
        }

        for(i=0;i<n;i++) {
            int* t = ht.get(i);
            if(t)
                cout<<*t<<endl;
            else
                cout<<"t is NULL"<<endl;
        }
    }

}

void test11() {
    Hashtable<std::string,std::string> ht;

    ht.insert("test1","test111");
    ht.insert("test2","test222");

    ht["test3"] = "test333444";

    cout<<ht["test3"]<<endl;
    cout<<ht["test2"]<<endl;
}

class Stu {
public:
    int key1;
    int key2;
    string s;

    Stu() {

    }

    Stu(int k1,int k2,const char* s1):key1(k1),key2(k2),s(s1) {

    }

    ~Stu() {

    }
};

class Cmp {
public:
    int operator () (const Stu& st1,const Stu& st2) {
        return st1.key1 - st2.key1;
    }
};

class Hash {
public:
    unsigned int operator () (const Stu& st) {
        return st.key1 * st.key2 * 33 + st.key2 * st.key2;
    }
};

//Hashtable<Stu,Stu,Cmp,Hash> ht5;

void test12() {
#if 0
    Hashtable<char,char> ht;
    ht.insert('a','1');
    ht.insert('b','2');

    cout<<ht['b']<<endl;

    char* p = ht.get('a');
    cout<<*p<<endl;

    Hashtable<long long,long long> ht1;
    long long a= 11;
    long long b= 12;

    ht1.insert(a,b);

    cout<<ht1[a]<<endl;

    Hashtable<unsigned int,unsigned int> ht2;
    ht2.insert(100,200);

    cout<<ht2[100]<<endl;

    Hashtable<unsigned long,unsigned long> ht3;
    ht3.insert(123,234);

    cout<<ht3[123]<<endl;

    Hashtable<unsigned char,unsigned char> ht4;
    ht4.insert('f','g');

    cout<<ht4['f']<<endl;
#endif
    ////////////////////////////////////////////
    Hashtable<Stu,Stu,Cmp,Hash> ht5;
    Stu st1(100,200,"student1");Stu st11(1000,2000,"student10");
    Stu st2(101,203,"student2");Stu st22(1001,2003,"student20");
    Stu st3(102,206,"student3");Stu st33(1002,2006,"student30");

    ht5.insert(st1,st11);
    ht5.insert(st2,st22);
    ht5.insert(st3,st33);

    Stu* st = ht5.get(st3);
    if(st)
        cout<<st->key1<<" "<<st->key2<<" "<<st->s<<endl;
    else
        cout<<"not found!"<<endl;

}

int main()
{
//    MemPool* pool = MemPool::getInstance();

//    char* p = (char*)pool->_calloc(10);

//    memcpy(p,"test123",sizeof("test123") - 1);

//    cout<<p<<endl;

//    pool->_free(p);

//    test1(pool);
//    test2();
//    test3();
//    test4();
//    test5();
//    test6();
//    test7();
//    test8();
//    test9();
//    test10();
//    test11();
    test12();

	return 0;
}
